/*
*********************************************************************************************************
*                                                uC/GUI
*                        Universal graphic software for embedded applications
*
*                       (c) Copyright 2002, Micrium Inc., Weston, FL
*                       (c) Copyright 2002, SEGGER Microcontroller Systeme GmbH
*
*              µC/GUI is protected by international copyright laws. Knowledge of the
*              source code may not be used to write a similar product. This file may
*              only be used in accordance with a license and should not be redistributed
*              in any way. We appreciate your understanding and fairness.
*
----------------------------------------------------------------------
File        : LCDDummy.C
Purpose     : Empty driver
This driver does no perform any function, but it can be
used for 2 purposes:
a) Satisfy all externals so an application can be
compiled and linked in target hardware even if the
driver is not already available
b) Template for a starting point for a new driver.
----------------------------------------------------------------------
Adapting to a new system (creating a new driver):
In this case, the first step is to fill the routines
LCD_L0_GetPixelIndex, LCD_L0_SetPixelIndex and LCD_L0_Init with
functionality, which is sufficient to make the hardware work.
A second (optional) step would be to optimize higher level routines.
----------------------------------------------------------------------
Version-Date---Author-Explanation
----------------------------------------------------------------------
1.00.00 020417 JE     a) Changed to have only to adapt _GetPixelIndex
and _SetPixelIndex
0.90.00 020214 JE     a) First release
*/

#include "LCD_Private.h"      /* private modul definitions & config */
#include "GUI_Private.h"
#include "GUIDebug.h"

// Menglong Woo
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <pthread.h>
// #include <stdlib.h>
// #include <sys/ioctl.h>
short *fb_map = NULL;

#if (LCD_CONTROLLER == -1) \
&& (!defined(WIN32) | defined(LCD_SIMCONTROLLER))

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/

#ifndef LCD_INIT_CONTROLLER
	#define LCD_INIT_CONTROLLER()
#endif

/*********************************************************************
*
*       Macros for MIRROR_, SWAP_ and LUT_
*/
#if (!defined (LCD_LUT_COM) && !defined(LCD_LUT_SEG))
	#if   (!LCD_MIRROR_X && !LCD_MIRROR_Y && !LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) x
		#define LOG2PHYS_Y(x, y) y
	#elif (!LCD_MIRROR_X && !LCD_MIRROR_Y &&  LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) y
		#define LOG2PHYS_Y(x, y) x
	#elif (!LCD_MIRROR_X &&  LCD_MIRROR_Y && !LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) x
		#define LOG2PHYS_Y(x, y) LCD_YSIZE - 1 - (y)
	#elif (!LCD_MIRROR_X &&  LCD_MIRROR_Y &&  LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) y
		#define LOG2PHYS_Y(x, y) LCD_XSIZE - 1 - (x)
	#elif ( LCD_MIRROR_X && !LCD_MIRROR_Y && !LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) LCD_XSIZE - 1 - (x)
		#define LOG2PHYS_Y(x, y) y
	#elif ( LCD_MIRROR_X && !LCD_MIRROR_Y &&  LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) LCD_YSIZE - 1 - (y)
		#define LOG2PHYS_Y(x, y) x
	#elif ( LCD_MIRROR_X &&  LCD_MIRROR_Y && !LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) LCD_XSIZE - 1 - (x)
		#define LOG2PHYS_Y(x, y) LCD_YSIZE - 1 - (y)
	#elif ( LCD_MIRROR_X &&  LCD_MIRROR_Y &&  LCD_SWAP_XY)
		#define LOG2PHYS_X(x, y) LCD_YSIZE - 1 - (y)
		#define LOG2PHYS_Y(x, y) LCD_XSIZE - 1 - (x)
	#endif
#else
	#if   ( defined (LCD_LUT_COM) && !defined(LCD_LUT_SEG))
		#define LOG2PHYS_X(x, y) x
		#define LOG2PHYS_Y(x, y) LCD__aLine2Com0[y]
	#elif (!defined (LCD_LUT_COM) &&  defined(LCD_LUT_SEG))
		#define LOG2PHYS_X(x, y) LCD__aCol2Seg0[x]
		#define LOG2PHYS_Y(x, y) y
	#elif ( defined (LCD_LUT_COM) &&  defined(LCD_LUT_SEG))
		#define LOG2PHYS_X(x, y) LCD__aCol2Seg0[x]
		#define LOG2PHYS_Y(x, y) LCD__aLine2Com0[y]
	#endif
#endif


/*********************************************************************
*
*       Static functions
*
**********************************************************************
*/


/*********************************************************************
*
*       Draw Bitmap 1 BPP
*/
static void  _DrawBitLine1BPP(int x, int y, U8 const GUI_UNI_PTR *p, int Diff, int xsize, const LCD_PIXELINDEX *pTrans)
{
	LCD_PIXELINDEX Index0 = *(pTrans + 0);
	LCD_PIXELINDEX Index1 = *(pTrans + 1);
	x += Diff;
	switch (GUI_Context.DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR)) {
	case 0:
		do {
			LCD_L0_SetPixelIndex(x++, y, (*p & (0x80 >> Diff)) ? Index1 : Index0);
			if (++Diff == 8) {
				Diff = 0;
				p++;
			}
		} while (--xsize);
		break;
	case LCD_DRAWMODE_TRANS:
		do {
			if (*p & (0x80 >> Diff)) {
				LCD_L0_SetPixelIndex(x, y, Index1);
			}
			x++;
			if (++Diff == 8) {
				Diff = 0;
				p++;
			}
		} while (--xsize);
		break;
	case LCD_DRAWMODE_XOR | LCD_DRAWMODE_TRANS:
	case LCD_DRAWMODE_XOR:
		do {
			if (*p & (0x80 >> Diff)) {
				int Pixel = LCD_L0_GetPixelIndex(x, y);
				LCD_L0_SetPixelIndex(x, y, LCD_NUM_COLORS - 1 - Pixel);
			}
			x++;
			if (++Diff == 8) {
				Diff = 0;
				p++;
			}
		} while (--xsize);
		break;
	}
}

/*********************************************************************
*
*       Draw Bitmap 2 BPP
*/
#if (LCD_MAX_LOG_COLORS > 2)
static void  _DrawBitLine2BPP(int x, int y, U8 const GUI_UNI_PTR *p, int Diff, int xsize, const LCD_PIXELINDEX *pTrans)
{
	LCD_PIXELINDEX Pixels = *p;
	int CurrentPixel = Diff;
	x += Diff;
	switch (GUI_Context.DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR)) {
	case 0:
		if (pTrans) {
			do {
				int Shift = (3 - CurrentPixel) << 1;
				int Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
				LCD_PIXELINDEX PixelIndex = *(pTrans + Index);
				LCD_L0_SetPixelIndex(x++, y, PixelIndex);
				if (++CurrentPixel == 4) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		} else {
			do {
				int Shift = (3 - CurrentPixel) << 1;
				int Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
				LCD_L0_SetPixelIndex(x++, y, Index);
				if (++CurrentPixel == 4) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		}
		break;
	case LCD_DRAWMODE_TRANS:
		if (pTrans) {
			do {
				int Shift = (3 - CurrentPixel) << 1;
				int Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
				if (Index) {
					LCD_PIXELINDEX PixelIndex = *(pTrans + Index);
					LCD_L0_SetPixelIndex(x, y, PixelIndex);
				}
				x++;
				if (++CurrentPixel == 4) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		} else {
			do {
				int Shift = (3 - CurrentPixel) << 1;
				int Index = (Pixels & (0xC0 >> (6 - Shift))) >> Shift;
				if (Index) {
					LCD_L0_SetPixelIndex(x, y, Index);
				}
				x++;
				if (++CurrentPixel == 4) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		}
		break;
	}
}
#endif

/*********************************************************************
*
*       Draw Bitmap 4 BPP
*/
#if (LCD_MAX_LOG_COLORS > 4)
static void  _DrawBitLine4BPP(int x, int y, U8 const GUI_UNI_PTR *p, int Diff, int xsize, const LCD_PIXELINDEX *pTrans)
{
	LCD_PIXELINDEX Pixels = *p;
	int CurrentPixel = Diff;
	x += Diff;
	switch (GUI_Context.DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR)) {
	case 0:
		if (pTrans) {
			do {
				int Shift = (1 - CurrentPixel) << 2;
				int Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
				LCD_PIXELINDEX PixelIndex = *(pTrans + Index);
				LCD_L0_SetPixelIndex(x++, y, PixelIndex);
				if (++CurrentPixel == 2) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		} else {
			do {
				int Shift = (1 - CurrentPixel) << 2;
				int Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
				LCD_L0_SetPixelIndex(x++, y, Index);
				if (++CurrentPixel == 2) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		}
		break;
	case LCD_DRAWMODE_TRANS:
		if (pTrans) {
			do {
				int Shift = (1 - CurrentPixel) << 2;
				int Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
				if (Index) {
					LCD_PIXELINDEX PixelIndex = *(pTrans + Index);
					LCD_L0_SetPixelIndex(x, y, PixelIndex);
				}
				x++;
				if (++CurrentPixel == 2) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		} else {
			do {
				int Shift = (1 - CurrentPixel) << 2;
				int Index = (Pixels & (0xF0 >> (4 - Shift))) >> Shift;
				if (Index) {
					LCD_L0_SetPixelIndex(x, y, Index);
				}
				x++;
				if (++CurrentPixel == 2) {
					CurrentPixel = 0;
					Pixels = *(++p);
				}
			} while (--xsize);
		}
		break;
	}
}
#endif

/*********************************************************************
*
*       Draw Bitmap 8 BPP
*/
#if (LCD_MAX_LOG_COLORS > 16)
static void  _DrawBitLine8BPP(int x, int y, U8 const GUI_UNI_PTR *p, int xsize, const LCD_PIXELINDEX *pTrans)
{
	LCD_PIXELINDEX Pixel;
	switch (GUI_Context.DrawMode & (LCD_DRAWMODE_TRANS | LCD_DRAWMODE_XOR)) {
	case 0:
		if (pTrans) {
			for (; xsize > 0; xsize--, x++, p++) {
				Pixel = *p;
				LCD_L0_SetPixelIndex(x, y, *(pTrans + Pixel));
			}
		} else {
			for (; xsize > 0; xsize--, x++, p++) {
				LCD_L0_SetPixelIndex(x, y, *p);
			}
		}
		break;
	case LCD_DRAWMODE_TRANS:
		if (pTrans) {
			for (; xsize > 0; xsize--, x++, p++) {
				Pixel = *p;
				if (Pixel) {
					LCD_L0_SetPixelIndex(x, y, *(pTrans + Pixel));
				}
			}
		} else {
			for (; xsize > 0; xsize--, x++, p++) {
				Pixel = *p;
				if (Pixel) {
					LCD_L0_SetPixelIndex(x, y, Pixel);
				}
			}
		}
		break;
	}
}
#endif

/*********************************************************************
*
*       Draw Bitmap 16 BPP
*/
#if (LCD_BITSPERPIXEL > 8)
static void  DrawBitLine16BPP(int x, int y, U16 const GUI_UNI_PTR *p, int xsize, const LCD_PIXELINDEX *pTrans)
{
	LCD_PIXELINDEX pixel;
	if ((GUI_Context.DrawMode & LCD_DRAWMODE_TRANS) == 0) {
		if (pTrans) {
			for (; xsize > 0; xsize--, x++, p++) {
				pixel = *p;
				LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));
			}
		} else {
			for (; xsize > 0; xsize--, x++, p++) {
				LCD_L0_SetPixelIndex(x, y, *p);
			}
		}
	} else {
		if (pTrans) {
			for (; xsize > 0; xsize--, x++, p++) {
				pixel = *p;
				if (pixel) {
					LCD_L0_SetPixelIndex(x, y, *(pTrans + pixel));
				}
			}
		} else {
			for (; xsize > 0; xsize--, x++, p++) {
				pixel = *p;
				if (pixel) {
					LCD_L0_SetPixelIndex(x, y, pixel);
				}
			}
		}
	}
}
#endif

/*********************************************************************
*
*       Exported functions
*
**********************************************************************
*/

/*********************************************************************
*
*       LCD_L0_SetPixelIndex
*
* Purpose:
*   Sets the index of the given pixel. The upper layers
*   calling this routine make sure that the coordinates are in range, so
*   that no check on the parameters needs to be performed.
*/
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)
{
	/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
	int xPhys = LOG2PHYS_X(x, y);
	int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif

	/* Write into hardware ... Adapt to your system */
	{
		/* ... */
		*(fb_map + LCD_XSIZE * y + x) = PixelIndex;
	}
}

/*********************************************************************
*
*       LCD_L0_GetPixelIndex
*
* Purpose:
*   Returns the index of the given pixel. The upper layers
*   calling this routine make sure that the coordinates are in range, so
*   that no check on the parameters needs to be performed.
*/
unsigned int LCD_L0_GetPixelIndex(int x, int y)
{
	LCD_PIXELINDEX PixelIndex;
	/* Convert logical into physical coordinates (Dep. on LCDConf.h) */
#if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y
	int xPhys = LOG2PHYS_X(x, y);
	int yPhys = LOG2PHYS_Y(x, y);
#else
#define xPhys x
#define yPhys y
#endif
	/* Read from hardware ... Adapt to your system */
	{
		// PixelIndex = 0;/* ... */
		// PixelIndex = LCD_GetPoint(x,y);
		// PixelIndex = 0;
		PixelIndex = *(fb_map + y * LCD_XSIZE + x);
	}
	return PixelIndex;
}

/*********************************************************************
*
*       LCD_L0_XorPixel
*/
void LCD_L0_XorPixel(int x, int y)
{
	LCD_PIXELINDEX PixelIndex = LCD_L0_GetPixelIndex(x, y);
	LCD_L0_SetPixelIndex(x, y, LCD_NUM_COLORS - PixelIndex - 1);
}

/*********************************************************************
*
*       LCD_L0_DrawHLine
*/
void LCD_L0_DrawHLine  (int x0, int y,  int x1)
{
#if 0
	if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
		for (; x0 <= x1; x0++) {
			LCD_L0_XorPixel(x0, y);
		}
	} else {
		for (; x0 <= x1; x0++) {
			LCD_L0_SetPixelIndex(x0, y, LCD_COLORINDEX);
		}
	}
#else
	if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
		for (; x0 <= x1; x0++) {
			LCD_L0_XorPixel(x0, y);
		}
	} else {
		register short *tmap = fb_map + y * LCD_XSIZE + x0;
		for (; x0 <= x1; x0++) {
			*tmap++ = LCD_COLORINDEX;
		}
	}
#endif
}
/*********************************************************************
*
*       LCD_L0_DrawVLine
*/
void LCD_L0_DrawVLine  (int x, int y0,  int y1)
{

#if 0
	if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
		for (; y0 <= y1; y0++) {
			LCD_L0_XorPixel(x, y0);
		}
	} else {
		for (; y0 <= y1; y0++) {
			LCD_L0_SetPixelIndex(x, y0, LCD_COLORINDEX);
		}
	}
#else
	register short *tmap;
	if (GUI_Context.DrawMode & LCD_DRAWMODE_XOR) {
		for (; y0 <= y1; y0++) {
			LCD_L0_XorPixel(x, y0);
		}
	} else {
		tmap = fb_map + y0 * LCD_XSIZE + x;
		for (; y0 <= y1; y0++) {
			*tmap = LCD_COLORINDEX;
			tmap += LCD_XSIZE;
		}
	}
#endif
}

/*********************************************************************
*
*       LCD_L0_FillRect
*/
void LCD_L0_FillRect(int x0, int y0, int x1, int y1)
{
#if 0
	for (; y0 <= y1; y0++) {
		LCD_L0_DrawHLine(x0, y0, x1);
	}
#else
	register short *tmap;
	register int tx;
	for (; y0 <= y1; y0++) {
		tmap = fb_map + y0 * LCD_XSIZE + x0;
		for (tx = x0; tx <= x1; tx++) {
			*tmap++ = LCD_COLORINDEX;
		}
	}
#endif


}

/*********************************************************************
*
*       LCD_L0_DrawBitmap
*/
void LCD_L0_DrawBitmap(int x0, int y0,
                       int xsize, int ysize,
                       int BitsPerPixel,
                       int BytesPerLine,
                       const U8 GUI_UNI_PTR *pData, int Diff,
                       const LCD_PIXELINDEX *pTrans)
{
	int i;
	/* Use _DrawBitLineXBPP */
	for (i = 0; i < ysize; i++) {
		switch (BitsPerPixel) {
		case 1:
			_DrawBitLine1BPP(x0, i + y0, pData, Diff, xsize, pTrans);
			break;
#if (LCD_MAX_LOG_COLORS > 2)
		case 2:
			_DrawBitLine2BPP(x0, i + y0, pData, Diff, xsize, pTrans);
			break;
#endif
#if (LCD_MAX_LOG_COLORS > 4)
		case 4:
			_DrawBitLine4BPP(x0, i + y0, pData, Diff, xsize, pTrans);
			break;
#endif
#if (LCD_MAX_LOG_COLORS > 16)
		case 8:
			_DrawBitLine8BPP(x0, i + y0, pData, xsize, pTrans);
			break;
#endif
#if (LCD_BITSPERPIXEL > 8)
		case 16:
			DrawBitLine16BPP(x0, i + y0, (const U16 *)pData, xsize, pTrans);
			break;
#endif
		}
		pData += BytesPerLine;
	}
}

/*********************************************************************
*
*       LCD_L0_SetOrg
*/
void LCD_L0_SetOrg(int x, int y)
{
	GUI_USE_PARA(x);
	GUI_USE_PARA(y);
}

/*********************************************************************
*
*       LCD_On / LCD_Off
*/
void LCD_On (void)
{
#ifdef LCD_ON
	LCD_ON();
#endif
}

void LCD_Off (void)
{
#ifdef LCD_OFF
	LCD_OFF();
#endif
}

/*********************************************************************
*
*       LCD_L0_Init
*
* Purpose:
*   Initialises the LCD-controller.
*/
int  LCD_L0_Init(void)
{
	//LCD_INIT_CONTROLLER();
	return 0;
}

/*********************************************************************
*
*       LCD_L0_SetLUTEntry
*/
void LCD_L0_SetLUTEntry(U8 Pos, LCD_COLOR Color)
{
	GUI_USE_PARA(Pos);
	GUI_USE_PARA(Color);
}

#else

void LCDDummy_c(void);
void LCDDummy_c(void) { } /* avoid empty object files */

#endif /* (LCD_CONTROLLER undefined) */


void GUI_X_Init(void)
{
	fbdev_mmap();
}

/**** ExecIdle - called if nothing else is left to do ****/
void GUI_X_ExecIdle(void)
{

}

/**** Timing routines - required for blinking ****/
unsigned long g_ucgui_time_ms;
int  GUI_X_GetTime(void)
{
	struct timeval tv;
	gettimeofday(&tv, NULL);
	return  tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
void GUI_X_Delay(int Period)
{

}

/**** Multitask routines - required only if multitasking is used (#define GUI_OS 1) ****/
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void GUI_X_Unlock(void)
{
	pthread_mutex_lock(&mutex);
}
void GUI_X_Lock(void)
{
	pthread_mutex_unlock(&mutex);
}
U32  GUI_X_GetTaskId(void)
{
	return 0;
}
void GUI_X_InitOS(void)
{

}

/****      Event driving (optional with multitasking)  ****/
void GUI_X_WaitEvent(void)
{

}
void GUI_X_SignalEvent(void)
{

}
/**** Recording (logs/warnings and errors) - required only for higher levels ****/
void GUI_X_Log(const char *s)
{

}
void GUI_X_Warn(const char *s)
{

}
void GUI_X_ErrorOut(const char *s)
{

}

void exit(int i)
{

}

// int DockDrop(WM_MESSAGE *pMsg)
// {
//   GUI_RECT rect;
//   static GUI_PID_STATE plast, pnew;
//   static unsigned long tmlast = 0,tmnow = 0;
//   // return ;
//   return 0;
// }




#define RED_COLOR565    0x0F800

#define GREEN_COLOR565  0x007E0

#define BLUE_COLOR565   0x0001F
#if 0
	#define RED_COLOR565    (0x10 << 11)
	#define GREEN_COLOR565  (0x20 << 5)
	#define BLUE_COLOR565   (0x10 << 0)
#endif

#include <linux/input.h>
char *device_keyboard   = "/dev/input/event0";			// 默认设备
char *device_touch   = "/dev/input/event2";			// 默认设备
#ifdef CONFIG_QT_PTY
	DlgPty *pg_pty = NULL;
#endif

void *thread_rdkeyboard(void *arg)
{
	int   fdinput          = 0;
	int   len              = 0;
	char *keystatus        = "unknow";
	char  str_console[128] = "";
	struct input_event event_status;


	fdinput = open(device_keyboard, O_RDONLY);
	if (fdinput < 0) {
		printf("fail open device %s\n", device_keyboard);
		return 0;
	}

	while(1) {
		len = read(fdinput, &event_status, sizeof(event_status));
		if (len != -1 && event_status.type == EV_KEY) {
			switch(event_status.value) {
			case 1:
				keystatus =     "down"  ;
				GUI_StoreKeyMsg(sc2_ucgui_vk(event_status.code), 1);
				break;
			case 2:
				keystatus =   "press" ;
				GUI_StoreKeyMsg(sc2_ucgui_vk(event_status.code), 1);
				break;
			case 0:
				keystatus =    "up"    ;
				GUI_StoreKeyMsg(sc2_ucgui_vk(event_status.code), 0);
				break;
			default:
				keystatus = "unknow";
				printf("code %x %x %x\n", event_status.code, event_status.value, event_status.type);
				break;
			}
			snprintf(str_console , sizeof(str_console),
			         "%s\t%x\t%s\r\n",
			         keystatus,
			         event_status.code,
			         disp_keyname(event_status.code));
			printf("%s", str_console);
		}
	}
	close(fdinput);
}


static struct adj_tp tpadj = {
	.A1 = -0.232412,
	.B1 = -0.00281956,
	.C1 = 810.46,
	.A2 = -0.003067,
	.B2 = 0.2079,
	.C2 = -187.56,
};

void tp_getadj(struct adj_tp *adj)
{
	adj->K = tpadj.K;
	adj->A1 = tpadj.A1;
	adj->B1 = tpadj.B1;
	adj->C1 = tpadj.C1;
	adj->A2 = tpadj.A2;
	adj->B2 = tpadj.B2;
	adj->C2 = tpadj.C2;
}

void tp_setadj(struct adj_tp *adj)
{
	tpadj.K = adj->K;
	tpadj.A1 = adj->A1;
	tpadj.B1 = adj->B1;
	tpadj.C1 = adj->C1;
	tpadj.A2 = adj->A2;
	tpadj.B2 = adj->B2;
	tpadj.C2 = adj->C2;
}

int xdata;
int ydata;
void GUI_TOUCH_X_ActivateX()
{
	// struct point pt;
	// TP_GetADC(&pt);
}
void GUI_TOUCH_X_ActivateY()
{
	// struct point pt;
	// TP_GetADC(&pt);
}
int  GUI_TOUCH_X_MeasureX(void)
{
	return xdata;
}
int  GUI_TOUCH_X_MeasureY(void)
{
	return ydata;
}
#include <GUIType.h>

#define MAXNUM (10)
extern void Gauss (double a[][MAXNUM], int n);
/**
 * @brief	3点校准算法
 * @param	lcd lcd坐标
 * @param	tp 触屏坐标
 * @retval	retadj
 * @remarks
 * @see
 */
void tp_adj(struct point *lcd, struct point *tp, struct adj_tp *retadj)
{
#define _Xd(c) ( (lcd+c)->x)
#define _Yd(c) ( (lcd+c)->y)
#define _X(c) ( (tp+c)->x)
#define _Y(c) ( (tp+c)->y)

#define _K	(retadj->K)
#define _A1	(retadj->A1)
#define _B1	(retadj->B1)
#define _C1	(retadj->C1)
#define _A2	(retadj->A2)
#define _B2	(retadj->B2)
#define _C2	(retadj->C2)


	// 3 点校准做算法
	_K = (_X(0) - _X(2)) * (_Y(1) - _Y(2)) - (_X(1) - _X(2)) * (_Y(0) - _Y(2));

	_A1 = ( (_Xd(0) - _Xd(2)) * (_Y(1) - _Y(2)) - (_Xd(1) - _Xd(2)) * (_Y(0) - _Y(2)) ) / _K;
	_B1 = ( (_X(0) - _X(2)) * (_Xd(1) - _Xd(2)) - (_Xd(0) - _Xd(2)) * (_X(1) - _X(2)) ) / _K;
	_C1 = ( _Y(0) * (_X(2) * _Xd(1) - _X(1) * _Xd(2)) +
	        _Y(1) * (_X(0) * _Xd(2) - _X(2) * _Xd(0)) +
	        _Y(2) * (_X(1) * _Xd(0) - _X(0) * _Xd(1))) / _K;

	_A2 = ( (_Yd(0) - _Yd(2)) * (_Y(1) - _Y(2)) - (_Yd(1) - _Yd(2)) * (_Y(0) - _Y(2)) ) / _K;
	_B2 = ( (_X(0) - _X(2)) * (_Yd(1) - _Yd(2)) - (_Yd(0) - _Yd(2)) * (_X(1) - _X(2)) ) / _K;
	_C2 = ( _Y(0) * (_X(2) * _Yd(1) - _X(1) * _Yd(2)) +
	        _Y(1) * (_X(0) * _Yd(2) - _X(2) * _Yd(0)) +
	        _Y(2) * (_X(1) * _Yd(0) - _X(0) * _Yd(1))) / _K;

	// printf("\n[%d %d %d %d %d %d %d ]\n", (
	// 	(int)(retadj->A1*1000), (int)(retadj->B1*1000), (int)(retadj->C1*1000),
	// 	(int)(retadj->A2*1000), (int)(retadj->B2*1000), (int)(retadj->C2*1000),
	// 	(int)(retadj->K*1000)));
	// _A1 = 10;
	// _B1 = 11;
	// _C1 = 12;
	// _A2 = 13;
	// _B2 = 14;
	// _C2 = 15;
	// _K = 16;
	printf("_A1 = %f\r\n", _A1);
	printf("_B1 = %f\r\n", _B1);
	printf("_C1 = %f\r\n", _C1);
	printf("_A2 = %f\r\n", _A2);
	printf("_B2 = %f\r\n", _B2);
	printf("_C2 = %f\r\n", _C2);
	printf("_K = %f\r\n", _K);


	double A[4][MAXNUM];
	// A[1][1] = 3214, A[1][2] = 1238, A[1][3] = 1, A[1][4] = 60;
	// A[2][1] = 977, A[2][2] = 1206, A[2][3] = 1, A[2][4] = 580;
	// A[3][1] = 3193, A[3][2] = 2950, A[3][3] = 1, A[3][4] = 60;
	A[1][1] = _X(0), A[1][2] = _Y(0), A[1][3] = 1, A[1][4] = _Xd(0);
	A[2][1] = _X(1), A[2][2] = _Y(1), A[2][3] = 1, A[2][4] = _Xd(1);
	A[3][1] = _X(2), A[3][2] = _Y(2), A[3][3] = 1, A[3][4] = _Xd(2);

	Gauss (A, 3);
#if 0
	for(int i = 1; i <= 3; i++) {
		printf("X%d=%f\n", i, A[i][4]);
	}
#endif
	_A1 = A[1][4];
	_B1 = A[2][4];
	_C1 = A[3][4];

	A[1][1] = _X(0), A[1][2] = _Y(0), A[1][3] = 1, A[1][4] = _Yd(0);
	A[2][1] = _X(1), A[2][2] = _Y(1), A[2][3] = 1, A[2][4] = _Yd(1);
	A[3][1] = _X(2), A[3][2] = _Y(2), A[3][3] = 1, A[3][4] = _Yd(2);

	Gauss (A, 3);
#if 0
	for(int i = 1; i <= 3; i++) {
		printf("Y%d=%f\n", i, A[i][4]);
	}
#endif
	_A2 = A[1][4];
	_B2 = A[2][4];
	_C2 = A[3][4];
}


static unsigned char event = 0;
static int ispress = 0;
static int ad_x, ad_y;
int tp_ispress()
{
	return ispress;
}
int gettouch(struct point *pt)
{

	if (event) {
		event = 0;
		pt->x = ad_x;
		pt->y = ad_y;
		// pt->Pressed = event;
		return 1;
	}
	return 0;
}
#define GATE_TC (15)

int fliter(int *x, int *y, int *ax, int *ay)
{
	int avx, avy;
	int det;
	avx = (x[0] + x[1]) >> 1;
	avy = (y[0] + y[1]) >> 1;

	*ax = avx;
	*ay = avy;
	return 1;

}
void *thread_rdtouch(void *arg)
{
	int   fdinput          = 0;
	int   len              = 0;
	char *keystatus        = "unknow";
	char  str_console[128] = "";
	struct input_event event_status;
	int bx = 0, by = 0;

	int ads_x[4], ads_y[4];
	int ads_i = 0;
	int isfirstdown = 0;
	int lxdata = 0,lydata = 0;

	fdinput = open(device_touch, O_RDONLY);
	if (fdinput < 0) {
		printf("fail open device touch %s\n", device_touch);
		return 0;
	}
	// int ad_x, ad_y;
	GUI_PID_STATE ts;
	while(1) {
		len = read(fdinput, &event_status, sizeof(event_status));
		if (len != -1 && event_status.type == EV_ABS) {
			switch(event_status.code) {
			case 0x18:
				if (event_status.value == 0x01) {
					keystatus =    "down" ;
				} else if(event_status.value == 0) {
					ispress = 0;
					GUI_TOUCH_StoreUnstable(xdata, ydata);
					GUI_TOUCH_Exec();
				} else {
					printf("code %x value %x type %x\n", event_status.code, event_status.value, event_status.type);
				}
				break;
			case ABS_X:
				keystatus =    "\t\tx" ;
				ad_y = event_status.value;
				ads_y[ads_i] = event_status.value;
				bx = 1;
				break;
			case ABS_Y:
				keystatus =  "\t\ty" ;
				ad_x = event_status.value;
				ads_x[ads_i] = event_status.value;
				// xdata = (tpadj.A1 * ad_x + tpadj.B1 * ad_y + tpadj.C1);
				by = 1;

				break;
			default:
				keystatus = "unknow";
				printf("code %x value %x type %x\n", event_status.code, event_status.value, event_status.type);
				break;
			}
			if (bx && by) {
				bx = by = 0;
				if (1) {

					xdata = (tpadj.A1 * ad_x + tpadj.B1 * ad_y + tpadj.C1);
					ydata = (tpadj.A2 * ad_x + tpadj.B2 * ad_y + tpadj.C2);
					printf("ad (%d,%d) log(%d,%d)\n", ad_x, ad_y, xdata, ydata);
					ispress = 1;
					event = 1;
					ts.Pressed = 1;
					ts.x = xdata;
					ts.y = ydata;
					GUI_TOUCH_StoreState(xdata, ydata);
					GUI_TOUCH_Exec();
				}
			}
		}
	}
	close(fdinput);
}

int fbdev_mmap()
{
	int fd_fb = 0;
	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	long int screen_size = 0;


	fd_fb = open("/dev/fb0", O_RDWR);
	if (!fd_fb) {
		printf("Error: cannot open framebuffer device.\n");
		exit(1);
	}

	// Get fixed screen info
	if (ioctl(fd_fb, FBIOGET_FSCREENINFO, &finfo)) {
		printf("Error reading fixed information.\n");
		exit(2);
	}

	// Get variable screen info
	if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &vinfo)) {
		printf("Error reading variable information.\n");
		exit(3);
	}

	// the size of the screen in bytes
	screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
	// test_rgb(fd_fb, screen_size, vinfo);
	if(vinfo.bits_per_pixel == 16) {
		// map framebuffer to user memory
		fb_map = (short *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
		if ((int)fb_map == -1) {
			printf("Error: failed to map framebuffer device to memory.\n");
			exit(4);
		}
	}
	static pthread_t g_readtimeout;
	pthread_create(&g_readtimeout, NULL, thread_rdkeyboard, NULL);
	pthread_create(&g_readtimeout, NULL, thread_rdtouch, NULL);
}